package org.spring.springboot.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.sql.Timestamp;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.spring.springboot.config.JSONPObject;
import org.spring.springboot.domain.User;
import org.spring.springboot.domain.WechatUtil;
import org.spring.springboot.service.OrdermService;
import org.spring.springboot.service.StockService;
import org.spring.springboot.service.StoreService;
import org.spring.springboot.service.UserService;
import org.spring.springboot.util.CheckoutUtil;
import org.spring.springboot.util.HttpUtil;
import org.spring.springboot.util.UnifiedOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;

@CrossOrigin
@RestController
@RequestMapping(value = "/store")
public class StoreController {
	
	@Autowired
	private StockService stockService;

	@Autowired
	private StoreService storeService;

	@Autowired
	private OrdermService ordermService;
	@Autowired
	private UserService userService;
	
	

	/**
	 * 通过货架ID查找商品信息
	 * 
	 * @param id
	 * @param callback
	 * @return
	 */
	@RequestMapping(value = "/goods", method = RequestMethod.GET)
	public JSONPObject goods(@RequestParam(value = "id", required = true) int id, String callback) {

		JSONObject data = new JSONObject();

		data.put("store", storeService.find(id));
		data.put("stock", stockService.findByStoreId(id));

		JSONObject result = new JSONObject();
		result.put("data", data);

		return new JSONPObject(callback, result);

	}

	/**
	 * 下order方法
	 * 
	 * @param orders
	 * @param callback
	 * @return
	 */
	@RequestMapping(value = "/order", method = RequestMethod.POST)
	public JSONPObject order(@RequestParam("orders") String orders, String callback) {

		JSONObject data = new JSONObject();

		data.put("id", ordermService.order(orders));
		return new JSONPObject(callback, data);

	}

	@RequestMapping(value = "/getOrder", method = RequestMethod.GET)
	public JSONPObject getOrder(@RequestParam(value = "id", required = true) int id, String callback) {

		JSONObject data = new JSONObject();

		data.put("data", ordermService.find(id));
		return new JSONPObject(callback, data);

	}

	@RequestMapping(value = "/getOrderByUserId", method = RequestMethod.GET)
	public JSONPObject getOrderByUserId(@RequestParam(value = "id", required = true) int id, String callback) {

		JSONObject data = new JSONObject();

		data.put("data", ordermService.find(id));
		return new JSONPObject(callback, data);

	}

	@RequestMapping(value = "/getVaildCode", method = RequestMethod.GET)
	public JSONPObject getVaildCode(@RequestParam(value = "phone", required = true) String phone, String callback) {

		JSONObject data = new JSONObject();
		try {
			userService.getVaildCode(phone);
		} catch (ClientException e) {
			data.put("data", "err");
			return new JSONPObject(callback, data);
		}

		data.put("data", "success");
		return new JSONPObject(callback, data);

	}

	@RequestMapping(value = "/doLogin", method = RequestMethod.POST)
	public JSONPObject doLogin(@RequestParam(value = "phone", required = true) String phone,
			@RequestParam(value = "code", required = true) String code, String callback) {

		JSONObject data = new JSONObject();
		data.put("data", userService.doLogin(phone, code));
		return new JSONPObject(callback, data);

	}

	@RequestMapping(value = "/userInfo", method = RequestMethod.GET)
	public JSONPObject userInfo(@RequestParam(value = "token", required = true) int id, String callback) {

		JSONObject data = new JSONObject();
		User user = userService.find(id);
		user.setPassword("");

		data.put("userInfo", user);
		data.put("orderm", ordermService.findByUid(id));
		return new JSONPObject(callback, data);

	}

	/**
	 * 微信token验证
	 * 
	 * @param model
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	@RequestMapping("/wx")
	public void hello(Model model, HttpServletRequest request, HttpServletResponse response) throws IOException {
		boolean isGet = request.getMethod().toLowerCase().equals("get");
		PrintWriter print;
		if (isGet) {
			// 微信加密签名
			String signature = request.getParameter("signature");
			// 时间戳
			String timestamp = request.getParameter("timestamp");
			// 随机数
			String nonce = request.getParameter("nonce");
			// 随机字符串
			String echostr = request.getParameter("echostr");
			// 通过检验signature对请求进行校验，若校验成功则原样返回echostr，表示接入成功，否则接入失败
			if (signature != null && CheckoutUtil.checkSignature(signature, timestamp, nonce)) {
				try {
					print = response.getWriter();
					print.write(echostr);
					print.flush();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

		}
	}

	/**
	 * 获取用户openid和ticket
	 * 
	 * @param code
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "/getOpenId", method = RequestMethod.GET)
	public JSON getOpenId(@RequestParam(value = "code", required = true) String code) throws IOException {
		String res = HttpUtil.sendGet("https://api.weixin.qq.com/sns/oauth2/access_token",
				"appid=wxa5d9f1e385acd50c&secret=2633db528cd48d455b15a9a044e01a80&code=" + code
						+ "&grant_type=authorization_code");

		JSONObject data = new JSONObject();
		data = JSONObject.parseObject(res);
		System.out.println(res);

		return data;

	}

	@RequestMapping(value = "/getConfig", method = RequestMethod.GET)
	public JSON getConfig(HttpServletRequest request) {

		
		JSONObject data = new JSONObject();
		if (System.currentTimeMillis() - WechatUtil.time > 3600 * 1000) {
			String access_tokenRes = HttpUtil.sendGet("https://api.weixin.qq.com/cgi-bin/token",
					"grant_type=client_credential&appid=wxa5d9f1e385acd50c&secret=2633db528cd48d455b15a9a044e01a80");
			String res2 = HttpUtil.sendGet("https://api.weixin.qq.com/cgi-bin/ticket/getticket",
					"access_token=" + JSONObject.parseObject(access_tokenRes).get("access_token") + "&type=jsapi");
			JSONObject data2 = new JSONObject();
			data2 = JSONObject.parseObject(res2);
			WechatUtil.ticket = data2.get("ticket").toString();
			WechatUtil.time = System.currentTimeMillis();
		}
		
		

	
			data.put("appId", "wxa5d9f1e385acd50c");
			data.put("timestamp",(System.currentTimeMillis()/1000)+"");
			data.put("nonceStr", UUID.randomUUID().toString().substring(0, 30));

			String contextpath = request.getScheme() + "://" + request.getServerName()+"/";

			data.put("signature",
					org.apache.commons.codec.digest.DigestUtils.sha1Hex("jsapi_ticket=" + WechatUtil.ticket + "&noncestr=" + data.getString("nonceStr")
							+ "&timestamp=" + data.getLongValue("timestamp") + "&url=" + contextpath));

		

		return data;

	}

	/**
	 * 发起统一下单接口和微信支付
	 * 
	 * @param openid
	 * @param fee
	 * @return
	 */
	@RequestMapping(value = "/pay", method = RequestMethod.GET)
	public Map<Object, Object> pay(String openid, int fee) {
		System.out.println(openid + ":" + fee*100);
		UnifiedOrder unifiedOrder = new UnifiedOrder();
		unifiedOrder.setAppid("wxa5d9f1e385acd50c");
		unifiedOrder.setAttach("hehedesk");

		unifiedOrder.setBody("hehedesk");
		unifiedOrder.setMch_id("1489948342");

		String nonce = UUID.randomUUID().toString().substring(0, 30);
		unifiedOrder.setNonce_str(nonce);
		unifiedOrder.setNotify_url("wwwwjwjwjj");

		unifiedOrder.setOpenid(openid);
		unifiedOrder.setOut_trade_no(nonce);

		unifiedOrder.setSpbill_create_ip("14.23.150.211");
		unifiedOrder.setTotal_fee(fee*100);

		String sign = createUnifiedOrderSign(unifiedOrder);
		unifiedOrder.setSign(sign);

		/**
		 * 转成XML格式
		 */
		XStream xStream = new XStream(new XppDriver(new NoNameCoder()) {

			@Override
			public PrettyPrintWriter createWriter(Writer out) {
				return new PrettyPrintWriter(out) {
					// 对所有xml节点的转换都增加CDATA标记
					boolean cdata = true;

					@Override
					@SuppressWarnings("rawtypes")
					public void startNode(String name, Class clazz) {
						super.startNode(name, clazz);
					}

					@Override
					public String encodeNode(String name) {
						return name;
					}

					@Override
					protected void writeText(QuickWriter writer, String text) {
						if (cdata) {
							writer.write("<![CDATA[");
							writer.write(text);
							writer.write("]]>");
						} else {
							writer.write(text);
						}
					}
				};
			}
		});
		xStream.alias("xml", unifiedOrder.getClass());

		String response;
		String xml = xStream.toXML(unifiedOrder);

		try {
			SAXReader reader = new SAXReader();

			response = HttpUtil.post("https://api.mch.weixin.qq.com/pay/unifiedorder", xml);

			Document doc = DocumentHelper.parseText(response);
			Element root = doc.getRootElement();

			SortedMap<Object, Object> signMap = new TreeMap<>();

			signMap.put("appId", "wxa5d9f1e385acd50c");
			signMap.put("timeStamp", System.currentTimeMillis() + "");
			signMap.put("nonceStr", UUID.randomUUID().toString().substring(0, 30));
			signMap.put("package", "prepay_id=" + root.elementText("prepay_id"));
			signMap.put("signType", "MD5");
			StringBuffer sign2 = new StringBuffer();

			sign2.append("appId=").append(signMap.get("appId"));
			sign2.append("&nonceStr=").append(signMap.get("nonceStr"));
			sign2.append("&package=").append(signMap.get("package"));
			sign2.append("&signType=").append(signMap.get("signType"));
			sign2.append("&timeStamp=").append(signMap.get("timeStamp"));
			sign2.append("&key=").append("blankblankblankblankblankblank11");

			signMap.put("paySign", DigestUtils.md5DigestAsHex((sign2.toString()).getBytes()).toUpperCase());

			return signMap;

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return null;

	}

	public String createUnifiedOrderSign(UnifiedOrder unifiedOrder) {
		StringBuffer sign = new StringBuffer();
		sign.append("appid=").append(unifiedOrder.getAppid());
		sign.append("&attach=").append(unifiedOrder.getAttach());
		sign.append("&body=").append(unifiedOrder.getBody());
		sign.append("&device_info=").append(unifiedOrder.getDevice_info());
		sign.append("&mch_id=").append(unifiedOrder.getMch_id());
		sign.append("&nonce_str=").append(unifiedOrder.getNonce_str());
		sign.append("&notify_url=").append(unifiedOrder.getNotify_url());
		sign.append("&openid=").append(unifiedOrder.getOpenid());
		sign.append("&out_trade_no=").append(unifiedOrder.getOut_trade_no());
		sign.append("&spbill_create_ip=").append(unifiedOrder.getSpbill_create_ip());
		sign.append("&total_fee=").append(unifiedOrder.getTotal_fee());
		sign.append("&trade_type=").append(unifiedOrder.getTrade_type());
		sign.append("&key=").append("blankblankblankblankblankblank11");

		return DigestUtils.md5DigestAsHex((sign.toString()).getBytes()).toUpperCase();
	}

}
